const path = require('path');
const chokidar = require('chokidar');
const chalk = require('chalk');
const Mock = require('mockjs');
const express = require('express');

const mockDir = path.join(process.cwd(), 'mocks');

/**
 * 注册路由
 * @param {*} app
 */
function registerRoutes(app) {
  let mockLastIndex;
  const { mocks } = require('./material/index');
  const mocksForServer = mocks.map(route => {
    return responseFake(route.url, route.type, route.response);
  });
  for (const mock of mocksForServer) {
    app[mock.type](mock.url, mock.response);
    mockLastIndex = app._router.stack.length;
  }
  const mockRoutesLength = Object.keys(mocksForServer).length;
  return {
    mockRoutesLength: mockRoutesLength,
    mockStartIndex: mockLastIndex - mockRoutesLength,
  };
}

function unregisterRoutes() {
  Object.keys(require.cache).forEach(i => {
    if (i.includes(mockDir)) {
      delete require.cache[require.resolve(i)];
    }
  });
}

// for mock server
const responseFake = (url, type, respond) => {
  return {
    url: new RegExp(`${process.env.VUE_APP_API_PREFIX}${url}`),
    type: type || 'get',
    response(req, res) {
      console.log('request invoke:' + req.path);
      res.json(
        Mock.mock(respond instanceof Function ? respond(req, res) : respond),
      );
    },
  };
};

module.exports = app => {
  // https://expressjs.com/en/4x/api.html#req.body
  app.use(express.json()); // for parsing application/json
  app.use(express.urlencoded({ extended: true })); //

  const mockRoutes = registerRoutes(app);
  var mockRoutesLength = mockRoutes.mockRoutesLength;
  var mockStartIndex = mockRoutes.mockStartIndex;

  // 监听文件变化，然后重启 server
  chokidar
    .watch(mockDir, {
      ignoreInitial: true,
    })
    .on('all', (event, path) => {
      if (event === 'change' || event === 'add') {
        try {
          // remove mock routes stack
          app._router.stack.splice(mockStartIndex, mockRoutesLength);

          // clear routes cache
          unregisterRoutes();

          const mockRoutes = registerRoutes(app);
          mockRoutesLength = mockRoutes.mockRoutesLength;
          mockStartIndex = mockRoutes.mockStartIndex;

          console.log(
            chalk.magentaBright(
              `\n > Mock Server hot reload success! changed  ${path}`,
            ),
          );
        } catch (error) {
          console.log(chalk.redBright(error));
        }
      }
    });
};
